import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/foundation.dart';
import '../exceptions/app_exceptions.dart';
import '../utils/logger.dart';

class HiveStorage {
  static HiveStorage? _instance;
  static HiveStorage get instance => _instance ??= HiveStorage._internal();
  
  bool _isInitialized = false;
  
  HiveStorage._internal();

  Future<void> init() async {
    if (_isInitialized) return;
    
    try {
      if (kIsWeb) {
        // Web平台使用默认的Hive初始化
        await Hive.initFlutter();
        _isInitialized = true;
        AppLogger.info('Hive initialized for web platform');
      } else {
        // 移动端使用应用程序文档目录
        final appDocumentDir = await getApplicationDocumentsDirectory();
        await Hive.initFlutter(appDocumentDir.path);
        _isInitialized = true;
        AppLogger.info('Hive initialized at: ${appDocumentDir.path}');
      }
    } catch (e) {
      AppLogger.error('Failed to initialize Hive', e);
      if (kIsWeb) {
        // Web平台初始化失败时尝试默认初始化
        try {
          await Hive.initFlutter();
          _isInitialized = true;
          AppLogger.info('Hive initialized with default settings for web');
        } catch (e2) {
          AppLogger.error('Failed to initialize Hive with default settings', e2);
          throw StorageException(
            message: 'Failed to initialize Hive',
            details: e.toString(),
          );
        }
      } else {
        throw StorageException(
          message: 'Failed to initialize Hive',
          details: e.toString(),
        );
      }
    }
  }

  // 确保已初始化
  void _ensureInitialized() {
    if (!_isInitialized) {
      throw StorageException(
        message: 'Hive not initialized. Call init() first.',
      );
    }
  }

  // 注册适配器
  void registerAdapter<T>(TypeAdapter<T> adapter) {
    try {
      _ensureInitialized();
      if (!Hive.isAdapterRegistered(adapter.typeId)) {
        Hive.registerAdapter(adapter);
        AppLogger.info('Registered adapter: ${adapter.typeId}');
      }
    } catch (e) {
      AppLogger.error('Failed to register adapter: ${adapter.typeId}', e);
      throw StorageException(
        message: 'Failed to register adapter',
        details: e.toString(),
      );
    }
  }

  // 打开Box
  Future<Box<T>> openBox<T>(String boxName) async {
    try {
      _ensureInitialized();
      if (Hive.isBoxOpen(boxName)) {
        return Hive.box<T>(boxName);
      }
      final box = await Hive.openBox<T>(boxName);
      AppLogger.info('Opened box: $boxName');
      return box;
    } catch (e) {
      AppLogger.error('Failed to open box: $boxName', e);
      throw StorageException(
        message: 'Failed to open box',
        details: e.toString(),
      );
    }
  }

  // 关闭Box
  Future<void> closeBox(String boxName) async {
    try {
      _ensureInitialized();
      if (Hive.isBoxOpen(boxName)) {
        await Hive.box(boxName).close();
        AppLogger.info('Closed box: $boxName');
      }
    } catch (e) {
      AppLogger.error('Failed to close box: $boxName', e);
      throw StorageException(
        message: 'Failed to close box',
        details: e.toString(),
      );
    }
  }

  // 删除Box
  Future<void> deleteBox(String boxName) async {
    try {
      _ensureInitialized();
      if (Hive.isBoxOpen(boxName)) {
        await Hive.box(boxName).close();
      }
      await Hive.deleteBoxFromDisk(boxName);
      AppLogger.info('Deleted box: $boxName');
    } catch (e) {
      AppLogger.error('Failed to delete box: $boxName', e);
      throw StorageException(
        message: 'Failed to delete box',
        details: e.toString(),
      );
    }
  }

  // 存储数据
  Future<void> put<T>(String boxName, dynamic key, T value) async {
    try {
      final box = await openBox<T>(boxName);
      await box.put(key, value);
      AppLogger.debug('Put data: $boxName[$key] = $value');
    } catch (e) {
      AppLogger.error('Failed to put data: $boxName[$key]', e);
      throw StorageException(
        message: 'Failed to put data',
        details: e.toString(),
      );
    }
  }

  // 获取数据
  Future<T?> get<T>(String boxName, dynamic key, [T? defaultValue]) async {
    try {
      final box = await openBox<T>(boxName);
      final value = box.get(key, defaultValue: defaultValue);
      AppLogger.debug('Get data: $boxName[$key] = $value');
      return value;
    } catch (e) {
      AppLogger.error('Failed to get data: $boxName[$key]', e);
      return defaultValue;
    }
  }

  // 删除数据
  Future<void> delete(String boxName, dynamic key) async {
    try {
      final box = await openBox(boxName);
      await box.delete(key);
      AppLogger.debug('Delete data: $boxName[$key]');
    } catch (e) {
      AppLogger.error('Failed to delete data: $boxName[$key]', e);
      throw StorageException(
        message: 'Failed to delete data',
        details: e.toString(),
      );
    }
  }

  // 检查键是否存在
  Future<bool> containsKey(String boxName, dynamic key) async {
    try {
      final box = await openBox(boxName);
      final result = box.containsKey(key);
      AppLogger.debug('Contains key: $boxName[$key] = $result');
      return result;
    } catch (e) {
      AppLogger.error('Failed to check key: $boxName[$key]', e);
      return false;
    }
  }

  // 获取所有键
  Future<Iterable<dynamic>> getKeys(String boxName) async {
    try {
      final box = await openBox(boxName);
      final keys = box.keys;
      AppLogger.debug('Get keys: $boxName = $keys');
      return keys;
    } catch (e) {
      AppLogger.error('Failed to get keys: $boxName', e);
      return [];
    }
  }

  // 获取所有值
  Future<Iterable<T>> getValues<T>(String boxName) async {
    try {
      final box = await openBox<T>(boxName);
      final values = box.values;
      AppLogger.debug('Get values: $boxName = $values');
      return values;
    } catch (e) {
      AppLogger.error('Failed to get values: $boxName', e);
      return [];
    }
  }

  // 获取Box长度
  Future<int> getLength(String boxName) async {
    try {
      final box = await openBox(boxName);
      final length = box.length;
      AppLogger.debug('Get length: $boxName = $length');
      return length;
    } catch (e) {
      AppLogger.error('Failed to get length: $boxName', e);
      return 0;
    }
  }

  // 清空Box
  Future<void> clear(String boxName) async {
    try {
      final box = await openBox(boxName);
      await box.clear();
      AppLogger.debug('Clear box: $boxName');
    } catch (e) {
      AppLogger.error('Failed to clear box: $boxName', e);
      throw StorageException(
        message: 'Failed to clear box',
        details: e.toString(),
      );
    }
  }

  // 批量写入
  Future<void> putAll<T>(String boxName, Map<dynamic, T> entries) async {
    try {
      final box = await openBox<T>(boxName);
      await box.putAll(entries);
      AppLogger.debug('Put all data: $boxName = ${entries.keys}');
    } catch (e) {
      AppLogger.error('Failed to put all data: $boxName', e);
      throw StorageException(
        message: 'Failed to put all data',
        details: e.toString(),
      );
    }
  }

  // 批量删除
  Future<void> deleteAll(String boxName, Iterable<dynamic> keys) async {
    try {
      final box = await openBox(boxName);
      await box.deleteAll(keys);
      AppLogger.debug('Delete all data: $boxName = $keys');
    } catch (e) {
      AppLogger.error('Failed to delete all data: $boxName', e);
      throw StorageException(
        message: 'Failed to delete all data',
        details: e.toString(),
      );
    }
  }

  // 压缩Box
  Future<void> compact(String boxName) async {
    try {
      final box = await openBox(boxName);
      await box.compact();
      AppLogger.debug('Compact box: $boxName');
    } catch (e) {
      AppLogger.error('Failed to compact box: $boxName', e);
      throw StorageException(
        message: 'Failed to compact box',
        details: e.toString(),
      );
    }
  }

  // 获取Box信息
  Future<Map<String, dynamic>> getBoxInfo(String boxName) async {
    try {
      final box = await openBox(boxName);
      final info = {
        'name': boxName,
        'path': box.path,
        'length': box.length,
        'keys': box.keys.toList(),
        'isEmpty': box.isEmpty,
        'isOpen': box.isOpen,
        'lazy': box.lazy,
      };
      AppLogger.debug('Get box info: $boxName = $info');
      return info;
    } catch (e) {
      AppLogger.error('Failed to get box info: $boxName', e);
      return {};
    }
  }

  // 监听Box变化
  Stream<BoxEvent> watch(String boxName, {dynamic key}) async* {
    try {
      final box = await openBox(boxName);
      yield* box.watch(key: key);
    } catch (e) {
      AppLogger.error('Failed to watch box: $boxName', e);
      throw StorageException(
        message: 'Failed to watch box',
        details: e.toString(),
      );
    }
  }

  // 获取所有Box名称
  List<String> getAllBoxNames() {
    try {
      _ensureInitialized();
      final boxNames = <String>[];
      // 这里需要手动维护box名称列表，因为Hive没有提供获取所有box名称的API
      // 可以通过文件系统扫描或者维护一个box名称列表
      AppLogger.debug('Get all box names: $boxNames');
      return boxNames;
    } catch (e) {
      AppLogger.error('Failed to get all box names', e);
      return [];
    }
  }

  // 关闭所有Box
  Future<void> closeAllBoxes() async {
    try {
      _ensureInitialized();
      await Hive.close();
      AppLogger.info('Closed all boxes');
    } catch (e) {
      AppLogger.error('Failed to close all boxes', e);
      throw StorageException(
        message: 'Failed to close all boxes',
        details: e.toString(),
      );
    }
  }

  // 删除Hive文件夹
  Future<void> deleteFromDisk() async {
    try {
      _ensureInitialized();
      await Hive.deleteFromDisk();
      _isInitialized = false;
      AppLogger.info('Deleted Hive from disk');
    } catch (e) {
      AppLogger.error('Failed to delete Hive from disk', e);
      throw StorageException(
        message: 'Failed to delete Hive from disk',
        details: e.toString(),
      );
    }
  }
}